/**
 * 代理模式 (Proxy Pattern)
 * 真实主题类，实际执行业务逻辑的对象
 */
class RealSubject {
  /**
   * 构造函数
   */
  constructor() {
    this.data = {}
  }

  /**
   * 获取数据
   * @param {string} key - 数据键
   * @returns {any} 对应的数据值
   */
  getData(key) {
    // TODO: 实现获取数据功能
    // 提示：返回指定key的数据
  }

  /**
   * 设置数据
   * @param {string} key - 数据键
   * @param {any} value - 数据值
   */
  setData(key, value) {
    // TODO: 实现设置数据功能
    // 提示：设置指定key的数据
  }

  /**
   * 删除数据
   * @param {string} key - 数据键
   */
  deleteData(key) {
    // TODO: 实现删除数据功能
    // 提示：删除指定key的数据
  }

  /**
   * 获取所有数据
   * @returns {Object} 所有数据的副本
   */
  getAllData() {
    // TODO: 实现获取所有数据功能
    // 提示：返回所有数据的副本
  }
}

/**
 * 代理类
 * 为真实主题提供代理功能，包括缓存和访问统计
 */
class ProxySubject {
  /**
   * 构造函数
   * @param {RealSubject} realSubject - 真实主题对象
   */
  constructor(realSubject) {
    this.realSubject = realSubject
    this.accessCount = 0
    this.cache = new Map()
  }

  /**
   * 代理获取数据
   * @param {string} key - 数据键
   * @returns {any} 数据值
   */
  getData(key) {
    // TODO: 实现代理获取数据功能
    // 提示：
    // 1. 增加访问计数
    // 2. 检查缓存
    // 3. 如果缓存中没有，从真实对象获取并缓存
    // 4. 返回数据
  }

  /**
   * 代理设置数据
   * @param {string} key - 数据键
   * @param {any} value - 数据值
   */
  setData(key, value) {
    // TODO: 实现代理设置数据功能
    // 提示：
    // 1. 增加访问计数
    // 2. 更新缓存
    // 3. 调用真实对象的设置方法
  }

  /**
   * 代理删除数据
   * @param {string} key - 数据键
   */
  deleteData(key) {
    // TODO: 实现代理删除数据功能
    // 提示：
    // 1. 增加访问计数
    // 2. 从缓存中删除
    // 3. 调用真实对象的删除方法
  }

  /**
   * 代理获取所有数据
   * @returns {Object} 所有数据
   */
  getAllData() {
    // TODO: 实现代理获取所有数据功能
    // 提示：
    // 1. 增加访问计数
    // 2. 调用真实对象的方法
  }

  /**
   * 获取访问统计
   * @returns {number} 访问次数
   */
  getAccessCount() {
    // TODO: 返回访问次数
  }

  /**
   * 清除缓存
   */
  clearCache() {
    // TODO: 清除所有缓存
  }

  /**
   * 获取缓存大小
   * @returns {number} 缓存中的条目数量
   */
  getCacheSize() {
    // TODO: 返回缓存中的条目数量
  }
}

/**
 * 虚拟代理 - 延迟加载
 * 只有在第一次访问时才创建真实对象
 */
class VirtualProxy {
  /**
   * 构造函数
   * @param {Function} createRealSubject - 创建真实对象的函数
   */
  constructor(createRealSubject) {
    this.createRealSubject = createRealSubject
    this.realSubject = null
  }

  /**
   * 获取真实对象
   * @returns {RealSubject} 真实主题对象
   */
  getRealSubject() {
    // TODO: 实现延迟加载
    // 提示：只有在第一次访问时才创建真实对象
  }

  /**
   * 代理getData调用
   * @param {string} key - 数据键
   * @returns {any} 数据值
   */
  getData(key) {
    // TODO: 代理getData调用
  }

  /**
   * 代理setData调用
   * @param {string} key - 数据键
   * @param {any} value - 数据值
   */
  setData(key, value) {
    // TODO: 代理setData调用
  }
}

module.exports = { RealSubject, ProxySubject, VirtualProxy }
